home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 February: Tool Chest / Apple Developer CD Series Tool Chest February 1996 (Apple Computer)(1996).iso / Sample Code / AppsToGo / DTS.StyleChat / AECustom.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-22  |  11.6 KB  |  423 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** File:        AECustom.c
  5. ** Written by:    Eric Soldan
  6. **
  7. ** Copyright © 1990-1991 Apple Computer, Inc.
  8. ** All rights reserved.
  9. */
  10.  
  11.  
  12.  
  13. /*****************************************************************************/
  14.  
  15.  
  16.  
  17. #include "App.h"            /* Get the application includes/typedefs, etc.    */
  18. #include "App.defs.h"        /* Get various application definitions.            */
  19. #include "App.protos.h"        /* Get the prototypes for application.            */
  20.  
  21. #ifndef __ERRORS__
  22. #include <Errors.h>
  23. #endif
  24.  
  25. #ifndef __TEXTEDITCONTROL__
  26. #include "TextEditControl.h"
  27. #endif
  28.  
  29. #ifndef __UTILITIES__
  30. #include "Utilities.h"
  31. #endif
  32.  
  33.  
  34.  
  35. /*****************************************************************************/
  36.  
  37.  
  38.  
  39. extern Boolean        gHasAppleEvents;
  40.     /* This is defined and initialized by the DTS.Lib..framework file AERequired.c.
  41.     ** This means that InitRequiredAppleEvents must be called prior to calling
  42.     ** InitConnectAppleEvents (a DTS.Lib..framework function), or before calling
  43.     ** InitCustomAppleEvents (a DTS.StyleChat function). */
  44.  
  45.  
  46. static pascal OSErr        ReceiveMessage(AppleEvent *message, AppleEvent *reply, long refcon);
  47.  
  48.  
  49.  
  50. /*****************************************************************************/
  51.  
  52.  
  53.  
  54. static AEHandler keywordsToInstall[] = {
  55.     { kCustomEventClass, keyAppMessage, (AEEventHandlerProcPtr)ReceiveMessage, nil }
  56. };        /* These are the custom AppleEvents. */
  57.  
  58. #define kNumKeywords (sizeof(keywordsToInstall) / sizeof(AEHandler))
  59.  
  60.  
  61.  
  62. /*****************************************************************************/
  63. /*****************************************************************************/
  64.  
  65. #ifdef applec
  66. #pragma segment AECustom
  67. #endif
  68.  
  69. /*****************************************************************************/
  70. /*****************************************************************************/
  71.  
  72.  
  73.  
  74. /* Install our custom AppleEvents.  This is done in addition to installing
  75. ** the required AppleEvents.  InitAppleEvents, which installs the required
  76. ** AppleEvents, must be called first, since it sets up some global values. */
  77.  
  78. void    InitCustomAppleEvents(void)
  79. {
  80.     OSErr    err;
  81.     short    i;
  82.  
  83.     if (gHasAppleEvents) {
  84.         for (i = 0; i < kNumKeywords; ++i) {
  85.  
  86.             if (!keywordsToInstall[i].theUPP)
  87.                 keywordsToInstall[i].theUPP = NewAEEventHandlerProc(keywordsToInstall[i].theHandler);
  88.  
  89.             err = AEInstallEventHandler(
  90.                 keywordsToInstall[i].theEventClass,    /* What class to install.  */
  91.                 keywordsToInstall[i].theEventID,    /* Keywords to install.    */
  92.                 keywordsToInstall[i].theUPP,        /* The AppleEvent handler. */
  93.                 0L,                                    /* Unused refcon.           */
  94.                 false                                /* Only for our app.       */
  95.             );
  96.  
  97.             if (err) {
  98.                 HCenteredAlert(rErrorAlert, nil, gAlertFilterUPP);
  99.                 return;
  100.             }
  101.         }
  102.     }
  103. }
  104.  
  105.  
  106.  
  107. /*****************************************************************************/
  108.  
  109.  
  110.  
  111. /* Send some type of message to the application we are connected to.  Most of the
  112. ** targeting information is the same for various different messages.  Given this,
  113. ** this function builds an AppleEvent, adds the common information to the AppleEvent,
  114. ** and then switches for the various different message types.  A similar factoring
  115. ** process is done at the receiving end. */
  116.  
  117. OSErr    SendMessage(FileRecHndl frHndl, short messageType)
  118. {
  119.     AEAddressDesc    remoteLoc;
  120.     OSErr            err;
  121.     AppleEvent        theAevt, reply;
  122.     long            windTag[2];
  123.     short            i;
  124.     WindowPtr        oldPort;
  125.     TEHandle        te;
  126.     char            hstate;
  127.     Handle            hText;
  128.     StScrpHandle    styl;
  129.     long            size;
  130.  
  131.     remoteLoc = (*frHndl)->connect.remoteLoc;
  132.  
  133.     if (!(*frHndl)->connect.connected) {
  134.         if (remoteLoc.dataHandle) {
  135.             AEDisposeDesc(&remoteLoc);
  136.             (*frHndl)->connect.remoteLoc.dataHandle = nil;
  137.         }
  138.         return(noErr);
  139.     }
  140.  
  141.     oldPort = SetFilePort(frHndl);
  142.  
  143.     theAevt.dataHandle = reply.dataHandle = nil;
  144.         /* Make sure disposing of the descriptors is okay in all cases. */
  145.         /* Even though the AppleEvent manager nils out the handle upon failure,
  146.         ** the below code doesn't necessarily call the AppleEvent manager for each
  147.         ** descriptor.  By etting them to nil here, this allows us to just try to
  148.         ** dispose of the descriptors at the bottom of the function. */
  149.  
  150.     err = AECreateAppleEvent(        /* CREATE EMPTY APPLEEVENT.     */
  151.         kCustomEventClass,            /* Event class.                 */
  152.         typeAppMessage,                /* Event ID.                 */
  153.         &remoteLoc,                    /* Address of receiving app. */
  154.         kAutoGenerateReturnID,        /* This value causes the     */
  155.                                     /* AppleEvent manager to     */
  156.                                     /* assign a return ID that     */
  157.                                     /* is unique to the session. */
  158.         kAnyTransactionID,            /* Ignore transaction ID.     */
  159.         &theAevt                    /* Location of event.         */
  160.     );
  161.  
  162.     if (!err)            /* Say what the message is. */
  163.         AEPutParamPtr(&theAevt,keyDirectObject, typeShortInteger, (Ptr)&messageType, sizeof(short));
  164.  
  165.     if (!err) {            /* Say what window message is for. */
  166.         for (i = 0; i < 2; ++i) windTag[i] = (*frHndl)->connect.windowTag[i];
  167.         AEPutParamPtr(&theAevt, keyWindowTag, typeDoubleLong, (Ptr)windTag, 2 * sizeof(long));
  168.     }
  169.  
  170.     /* The stuff that applies to all messages is now done.  Now specifically
  171.     ** handle all the different message types. */
  172.  
  173.     if (!err) {
  174.         switch (messageType) {
  175.  
  176.             case kDisconnectMssg:
  177.                     /* All the information we need is already in the AppleEvent. */
  178.                 break;
  179.  
  180.             case kTextMssg:
  181.                 te     = (*frHndl)->d.doc.outBox;
  182.                 hText  = (*te)->hText;
  183.                 hstate = LockHandleHigh(hText);
  184.                 size   = (*te)->teLength;
  185.                 err = AEPutParamPtr(
  186.                     &theAevt,
  187.                     keyAppMessage,
  188.                     typeTextMessage,
  189.                     *hText,
  190.                     size
  191.                 );
  192.                 HSetState(hText, hstate);
  193.                 break;
  194.  
  195.             case kStylMssg:
  196.                 styl = CTEGetFullStylScrap((*frHndl)->d.doc.outBox);
  197.                 if (styl) {
  198.                     LockHandleHigh((Handle)styl);
  199.                     size = GetHandleSize((Handle)styl);
  200.                     err = AEPutParamPtr(
  201.                         &theAevt,
  202.                         keyStylMessage,
  203.                         typeStylMessage,
  204.                         (Ptr)*styl,
  205.                         size
  206.                     );
  207.                     DisposeHandle((Handle)styl);
  208.                 }
  209.                 break;
  210.         }
  211.     }
  212.  
  213.     if (!err) {        /* If everything looks good... */
  214.         err = AESend(                    /* SEND APPLEEVENT.                */
  215.             &theAevt,                    /* Our Apple Event to send.        */
  216.             &reply,                        /* We may have a reply.            */
  217.             kAENoReply,                    /* Don't wait for reply.        */
  218.             kAENormalPriority,            /* App. send priority.            */
  219.             0,                            /* We aren't waiting.            */
  220.             nil,                        /* No wait, no filter.            */
  221.             nil                            /* EventFilterProcPtr.            */
  222.         );
  223.     }
  224.  
  225.     if (!err) {
  226.         switch (messageType) {
  227.             case kDisconnectMssg:
  228.                 (*frHndl)->connect.connected            = false;
  229.                 (*frHndl)->connect.remoteLoc.dataHandle = nil;
  230.                 (*frHndl)->connect.remotePath[0]        = 0;
  231.                 break;
  232.             case kTextMssg:
  233.                 CTESetSelect(0, (*te)->teLength, te);
  234.                     /* Select all the text so entering the next message is more convenient. */
  235.                 break;
  236.         }
  237.     }
  238.  
  239.     AEDisposeDesc(&theAevt);
  240.     AEDisposeDesc(&reply);
  241.         /* Dispose of the descriptors, created or not.  If not created, no harm done by calling. */
  242.  
  243.     SetPort(oldPort);
  244.     return(err);
  245. }
  246.  
  247.  
  248.  
  249. /*****************************************************************************/
  250.  
  251.  
  252.  
  253. static pascal OSErr    ReceiveMessage(AppleEvent *message, AppleEvent *reply, long refcon)
  254. {
  255. #ifndef __MWERKS__
  256. #pragma unused (reply, refcon)
  257. #endif
  258.  
  259.     OSErr            err;
  260.     short            messageType;
  261.     WindowPtr        window;
  262.     FileRecHndl        frHndl;
  263.     DescType        actualType;
  264.     long            actualSize, windTag[2];
  265.     AEAddressDesc    remoteLoc;
  266.     Handle            mssgData;
  267.     StScrpHandle    stylData;
  268.     TEHandle        te;
  269.     char            hstate;
  270.     long            mssgSize, stylSize;
  271.     ControlHandle    ctl;
  272.  
  273.     err = AEGetParamPtr(        /* GET THE MESSAGE TYPE.     */
  274.         message,                /* The AppleEvent.              */
  275.         keyDirectObject,        /* AEKeyword                 */
  276.         typeShortInteger,        /* Desired type.             */
  277.         &actualType,            /* Type code.                 */
  278.         (Ptr)&messageType,        /* Pointer to area for data. */ 
  279.         2 * sizeof(long),        /* Size of data area.         */
  280.         &actualSize                /* Returned size of data.     */
  281.     );
  282.  
  283.     if (!err) {
  284.         err = AEGetParamPtr(        /* GET WINDOW MESSAGE IS FOR. */
  285.             message,                /* The AppleEvent.               */
  286.             keyWindowTag,            /* AEKeyword                  */
  287.             typeDoubleLong,            /* Desired type.              */
  288.             &actualType,            /* Type code.                  */
  289.             (Ptr)windTag,            /* Pointer to area for data.  */ 
  290.             2 * sizeof(long),        /* Size of data area.          */
  291.             &actualSize                /* Returned size of data.      */
  292.         );
  293.     }
  294.  
  295.     if (!err) {            /* See if the requested window exists... */
  296.         window = GetAEWindow(windTag[1], windTag[0]);
  297.         if (window) {
  298.             frHndl = (FileRecHndl)GetWRefCon(window);
  299.                 /* The window still exists... */
  300.         }
  301.         else
  302.             err = userCanceledErr;
  303.                 /* User (or computer) canceled connection by disconnecting improperly. */
  304.     }
  305.  
  306.     if (!err) {        /* If everything is cool, then do the specific task... */
  307.  
  308.         switch(messageType) {
  309.  
  310.             case kDisconnectMssg:
  311.                 remoteLoc = (*frHndl)->connect.remoteLoc;
  312.                 AEDisposeDesc(&remoteLoc);
  313.                 (*frHndl)->connect.connected            = false;
  314.                 (*frHndl)->connect.remoteLoc.dataHandle = nil;
  315.                 (*frHndl)->connect.remotePath[0]        = 0;
  316.                 CNum2Ctl(window, 1020, &ctl);
  317.                 (*ctl)->contrlVis = false;
  318.                 BeginFrame(window);
  319.                 CNum2Ctl(window, 1010, &ctl);
  320.                 ShowStyledControl(ctl);
  321.                 CNum2Ctl(window, 1000, &ctl);
  322.                 (*ctl)->contrlVis = false;
  323.                 CNum2Ctl(window, 1002, &ctl);
  324.                 DoDraw1Control(ctl, false);
  325.                 EndFrame(window);
  326.                 break;
  327.  
  328.             case kTextMssg:
  329.                 if (!err) {        /* Determine the size of the data... */
  330.                     err = AEGetParamPtr(
  331.                         message,                /* The AppleEvent.              */
  332.                         keyAppMessage,            /* AEKeyword                 */
  333.                         typeTextMessage,        /* Desired type.             */
  334.                         &actualType,            /* Type code.                 */
  335.                         nil,                    /* Pointer to area for data. */ 
  336.                         0,                        /* Size of data area.         */
  337.                         &mssgSize                /* Returned size of data.     */
  338.                     );
  339.                 }
  340.                 mssgData = nil;
  341.                 if (!err) {        /* Get the data... */
  342.                     mssgData = NewHandle(mssgSize);
  343.                     if (mssgData) {
  344.                         hstate = LockHandleHigh(mssgData);
  345.                         err = AEGetParamPtr(
  346.                             message,                /* The AppleEvent.              */
  347.                             keyAppMessage,            /* AEKeyword                 */
  348.                             typeTextMessage,        /* Desired type.             */
  349.                             &actualType,            /* Type code.                 */
  350.                             *mssgData,                /* Pointer to area for data. */ 
  351.                             mssgSize,                /* Size of data area.         */
  352.                             &actualSize                /* Returned size of data.     */
  353.                         );
  354.                         HSetState(mssgData, hstate);
  355.                     }
  356.                     else err = memFullErr;
  357.                 }
  358.                 if (!err) {
  359.                     BeginContent(window);
  360.                         /* Clip out all but content portion of the window. */
  361.  
  362.                     te       = (*frHndl)->d.doc.inBox;
  363.                     stylData = (*frHndl)->d.doc.textStyl;
  364.                     mssgData = CTESwapText(te, mssgData, stylData, true);
  365.                     if (stylData) {
  366.                         DisposeHandle((Handle)stylData);
  367.                         (*frHndl)->d.doc.textStyl = nil;
  368.                     }
  369.  
  370.                     EndContent(window);
  371.                         /* Fix the window back to normal. */
  372.                 }
  373.  
  374.                 if (mssgData)
  375.                     DisposeHandle(mssgData);
  376.  
  377.                 if (!err)
  378.                     NotifyUser();
  379.  
  380.                 break;
  381.  
  382.             case kStylMssg:
  383.                 if (!err) {        /* Determine the size of the data... */
  384.                     err = AEGetParamPtr(
  385.                         message,                /* The AppleEvent.              */
  386.                         keyStylMessage,            /* AEKeyword                 */
  387.                         typeStylMessage,        /* Desired type.             */
  388.                         &actualType,            /* Type code.                 */
  389.                         nil,                    /* Pointer to area for data. */ 
  390.                         0,                        /* Size of data area.         */
  391.                         &stylSize                /* Returned size of data.     */
  392.                     );
  393.                 }
  394.                 stylData = nil;
  395.                 if (!err) {        /* Get the data... */
  396.                     stylData = (StScrpHandle)NewHandle(stylSize);
  397.                     if (stylData) {
  398.                         hstate = LockHandleHigh((Handle)stylData);
  399.                         err = AEGetParamPtr(
  400.                             message,                /* The AppleEvent.              */
  401.                             keyStylMessage,            /* AEKeyword                 */
  402.                             typeStylMessage,        /* Desired type.             */
  403.                             &actualType,            /* Type code.                 */
  404.                             (Ptr)*stylData,            /* Pointer to area for data. */ 
  405.                             stylSize,                /* Size of data area.         */
  406.                             &actualSize                /* Returned size of data.     */
  407.                         );
  408.                         HSetState((Handle)stylData, hstate);
  409.                         (*frHndl)->d.doc.textStyl = stylData;
  410.                     }
  411.                     else err = memFullErr;
  412.                 }
  413.                 break;
  414.  
  415.         }
  416.     }
  417.  
  418.     return(err);
  419. }
  420.  
  421.  
  422.  
  423.